package hu.vissy.yacap.display;

import com.google.common.base.Strings;

public class TextHelpRendererOptions {



    public enum SortMethod {
        UNSORTED, SHORT_FORM, LONG_FORM
    }

    /**
     * Default width of the text.
     */
    public static final int DEFAULT_WIDTH = 80;

    /**
     * Default indentation level of the option descriptions.
     */
    public static final int DEFAULT_INDENT = 16;

    /**
     * Default signature indentation level.
     */
    public static final int DEFAULT_SIGNATURE_INDENT = 8;

    /**
     * Maximum width of the text.
     */
    private int width = DEFAULT_WIDTH;

    /**
     * Indentation level of option descriptors.
     */
    private int indent = DEFAULT_INDENT;

    /**
     * Indentation level of the signature.
     */
    private int signatureIndent = DEFAULT_SIGNATURE_INDENT;

    /**
     * If true, all signature items (options) gets to a new line. Default is
     * false.
     */
    private boolean signatureSplit = false;

    /**
     * If true, an empty line will be placed after each option description.
     * Default is true.
     */
    private boolean separateBlocks = true;

    /**
     * Static text written before the signature.
     */
    private String signaturePrefix = "";

    /**
     * If true, the description of the unnamed parameters are displayed.
     */
    private boolean showUnnamedDescription = true;

    /**
     * If true, the internal parameters are displayed in signature.
     */
    private boolean showInternalParametersInSignature = false;

    /**
     * Optimization: the string used for indentation.
     */
    private String indentStr = "";

    /**
     * Optimization: the string used for signature indentation.
     */
    private String signIndentStr = "";

    /**
     * If true, shows all optional parameters in signature. If false, only the
     * required parameters are shown.
     */
    private boolean showOptionalOptionsInSignature = true;

    private SortMethod signatureSortMethod = SortMethod.UNSORTED;
    private SortMethod detailsSortMethod = SortMethod.UNSORTED;


    /**
     * Constructor.
     */
    public TextHelpRendererOptions() {
        calculate();
    }

    /**
     * Preprocessing for optimization.
     */
    private void calculate() {
        indentStr = Strings.repeat(" ", indent);
        signIndentStr = Strings.repeat(" ", signatureIndent);
    }

    /**
     * The display width.
     *
     * Default value is {@value #DEFAULT_WIDTH}.
     *
     * <p>
     * By default it is ensured that the output will not contain more characters
     * in any line than this value. However, there is one exception: if a single
     * word is longer than this value, it will extends.
     * </p>
     *
     * @param width
     *            The width to set.
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withWidth(int width) {
        this.width = width;
        calculate();
        return this;
    }

    /**
     * Sets the level of the indent of the option descriptions. Default value is
     * {@value #DEFAULT_INDENT}.
     *
     * <p>
     * This is the indent level of the descriptions. It reduces the display
     * width to be used for the descriptor.
     * </p>
     *
     * @param indent
     *            The level of indentation.
     * @return The configuration object itself.
     * @see TextHelpRendererOptions#setSignatureIndent(int)
     */
    public TextHelpRendererOptions withIndent(int indent) {
        this.indent = indent;
        calculate();
        return this;
    }



    /**
     * The prefix put before the first option in the signature. By default it is
     * empty.
     *
     * @param signaturePrefix
     *            The text to put in front of the signature.
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withSignaturePrefix(String signaturePrefix) {
        this.signaturePrefix = signaturePrefix;
        return this;
    }

    /**
     * Sets whether there should be an empty line between the option
     * descriptions. Default value is true.
     *
     * @param separateBlocks
     *            If true, an empty line will be placed between each option
     *            descriptor.
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withSeparateBlocks(boolean separateBlocks) {
        this.separateBlocks = separateBlocks;
        return this;
    }

    /**
     * Set whether the description of the unnamed options should be displayed.
     * Default value is true.
     *
     * @param showUnnamedDescription
     *            If true, the description of the unnamed parameters are
     *            displayed.
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withShowUnnamedDescription(boolean showUnnamedDescription) {
        this.showUnnamedDescription = showUnnamedDescription;
        return this;
    }

    /**
     * Set whether the internal parameters are shown in the signature. Default
     * value is false.
     *
     * @param showInternalParametersInSignature
     *            If true, the indication of possible internal parameters are
     *            shown in the signature.
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withShowInternalParametersInSignature(boolean showInternalParametersInSignature) {
        this.showInternalParametersInSignature = showInternalParametersInSignature;
        return this;
    }


    /**
     * Sets the level of the indent of the signature when it is split into
     * multiple lines. Default value is {@value #DEFAULT_SIGNATURE_INDENT}.
     *
     * <p>
     * This is the indent level of the signature when it is split into several
     * lines. It reduces the display width to be used for the signature.
     * </p>
     *
     * @param signatureIndent
     *            The level of indentation.
     * @return The configuration object itself.
     * @see TextHelpRendererOptions#setSignatureIndent(int)
     */
    public TextHelpRendererOptions withSignatureIndent(int signatureIndent) {
        this.signatureIndent = signatureIndent;
        calculate();
        return this;
    }

    /**
     * Sets whether the option elements in the signature should be put into
     * separated lines. Default value is false;
     *
     * @param split
     *            If true, each option in signature is placed into new lines.
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withSignatureSplit(boolean split) {
        signatureSplit = split;
        return this;
    }


    /**
     * Sets whether the optional parameters are shown in signature or not.
     *
     * @param showOptionalOptionsInSignature
     *            the showOptionalOptionsInSignature to set
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withShowOptionalOptionsInSignature(boolean showOptionalOptionsInSignature) {
        this.showOptionalOptionsInSignature = showOptionalOptionsInSignature;
        return this;
    }



    /**
     * @param signatureSortMethod
     *            The signature sort method.
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withSignatureSortMethod(SortMethod signatureSortMethod) {
        this.signatureSortMethod = signatureSortMethod;
        return this;
    }

    /**
     * @param detailsSortMethod
     *            The details sort method.
     * @return The configuration object itself.
     */
    public TextHelpRendererOptions withDetailsSortMethod(SortMethod detailsSortMethod) {
        this.detailsSortMethod = detailsSortMethod;
        return this;
    }

    /**
     * @return the width
     */
    public int getWidth() {
        return width;
    }

    /**
     * @return the indent
     */
    public int getIndent() {
        return indent;
    }

    /**
     * @return the signatureIndent
     */
    public int getSignatureIndent() {
        return signatureIndent;
    }

    /**
     * @return the signatureSplit
     */
    public boolean isSignatureSplit() {
        return signatureSplit;
    }

    /**
     * @return the separateBlocks
     */
    public boolean isSeparateBlocks() {
        return separateBlocks;
    }

    /**
     * @return the signaturePrefix
     */
    public String getSignaturePrefix() {
        return signaturePrefix;
    }

    /**
     * @return the showUnnamedDescription
     */
    public boolean isShowUnnamedDescription() {
        return showUnnamedDescription;
    }

    /**
     * @return the showInternalParametersInSignature
     */
    public boolean isShowInternalParametersInSignature() {
        return showInternalParametersInSignature;
    }

    /**
     * @return the indentStr
     */
    public String getIndentStr() {
        return indentStr;
    }

    /**
     * @return the signIndentStr
     */
    public String getSignIndentStr() {
        return signIndentStr;
    }

    /**
     * @return the showOptionalOptionsInSignature
     */
    public boolean isShowOptionalOptionsInSignature() {
        return showOptionalOptionsInSignature;
    }

    /**
     * @return the signatureSortMethod
     */
    public SortMethod getSignatureSortMethod() {
        return signatureSortMethod;
    }

    /**
     * @return the detailsSortMethod
     */
    public SortMethod getDetailsSortMethod() {
        return detailsSortMethod;
    }



}
